﻿#region Header

/*
Remote views based on linq
By

Pascal Hauser 
Dipl. Ing. in Informatik, Hochschule für Technik Rapperswil, 2006
Master Thesis, Hochschule für Technik Rapperswil, 2008-2010

and

Raphael Gfeller
Dipl. Ing. in Informatik, Hochschule für Technik Rapperswil, 2006
Master Thesis, Hochschule für Technik Rapperswil, 2008-2010

*/

#endregion

#region Usings

using System;
using System.Collections.Generic;
using System.Linq;
using System.Security;
using InterLinq;
using InterLinq.Services.Interface;
using Sebarf.Diagnostics.Interfaces;
using Sebastof.Services.Impl.DataHandlingStrategies;
using Sebastof.Services.Interfaces;

#endregion

namespace Sebastof.Services.Impl {
	/// <summary>
	/// Description of the class
	/// </summary>
	[Serializable]
	public class LazyLoadingDataHandlingStrategy<ResponsibleType> : IDataHandlingStrategy
		where ResponsibleType : SebastofApplicationObject {
		#region Public Properties

		public SebastofApplicationObject ResponsibleFor {
			get { return m_responsibleFor; }
		}

		#endregion

		#region Public Methods

		public LazyLoadingDataHandlingStrategy(ResponsibleType responsibleFor,
												IObservableCollectionCreatorService observableCollectionCreatorService) {
			m_responsibleFor = responsibleFor;
			m_observableCollectionCreatorService = observableCollectionCreatorService;
		}

		#endregion

		#region Private Methods

		// private methods located here

		#endregion

		#region Private Fields

		private readonly Dictionary<string, Object> m_data = new Dictionary<string, object>();
		private readonly IObservableCollectionCreatorService m_observableCollectionCreatorService;
		private readonly ResponsibleType m_responsibleFor;

		#endregion

		#region IDataHandlingStrategy Members

		public object GetValue(string key, object forObject) {
			return GetValue<Object>(key, forObject);
		}

		public T GetValue<T>(string key, object forObject) {
			if (m_data.ContainsKey(key)) {
				if (m_data[key] is AccessDeniedValue) {
					throw new SecurityException("no rights available for reading field: " + key);
				}
				return (T)m_data[key];
			}
			else {
				IQueryHandler queryHandler =
					m_responsibleFor.AttachedServiceLocatorService.GetRegisteredService<IQueryHandlerLocatorService>().GetQueryHandler
						();
				string id = m_responsibleFor.Id;
				string tmpKey = key;
				Logger.WriteDebug("Start loading lazy entry:" + key + " for object " + m_responsibleFor.Id);
				object value =
					(from s in queryHandler.GetTable<ResponsibleType>() where s.Id.Equals(id) select s.GetValue(tmpKey)).First();
				Logger.WriteDebug("End loading lazy entry:" + key + " for object " + m_responsibleFor.Id);
				m_data.Add(key, (T)m_observableCollectionCreatorService.ConvertToObservableCollection(value, forObject, key));
				return GetValue<T>(key, forObject);
			}
			Logger.WriteDebug("could not find value for " + key);
			return default(T);
		}

		public KeyValuePair<Object, KeyValuePair<string, object>[]>[] GetValues() {
			return new[] { new KeyValuePair<object, KeyValuePair<string, object>[]>(m_responsibleFor, m_data.ToArray()) };
		}

		public void SetValue(string key, object value, object forObject) {
			if (m_data.ContainsKey(key)) {
				m_data[key] = value;
			}
			else {
				m_data.Add(key, value);
			}
		}

		public bool IsDifferent(string key, object value, object forObject) {
			if (!m_data.ContainsKey(key)) {
				return false;
			}
			if (m_data[key] is AccessDeniedValue) {
				return false;
			}

			return (GetValue(key, forObject) != value);
		}

		#endregion
	}
}